﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace HRT.Procotol {
    /// <summary>
    /// 376.2 通信协议链路层通信方式，用于控制字段中
    /// </summary>
    /// <remarks>
    /// 通信方式是指集中器下行的通信模块所采用的通信方式类型，
    /// 不同的通信方式决定用户数据区中的数据构成和格式
    /// </remarks>
    enum QGDW1376_2CommuWay : Byte {
        /// <summary>
        /// 集中式路由载波通信
        /// </summary>
        CenRouCarrCommu = 1,
        /// <summary>
        /// 分布式路由载波通信
        /// </summary>
        DistributeRouteCarrCommu = 2,
        /// <summary>
        /// 宽带载波通信
        /// </summary>
        BroadCarrCommu = 3,
        /// <summary>
        /// 微功率无线通信
        /// </summary>
        MicroWirelesCommu = 10,
        /// <summary>
        /// 以太网通信
        /// </summary>
        EthCommu = 20
    };
    /// <summary>
    /// 查询时的通信方式，用于 AFN = 3 fn = 10 的上行规约
    /// </summary>
    enum QGDW1376_2QueryCommuWay : Byte {
        NarrowPowerCarrCommu = 1,
        BroadCarrCommu = 2,
        MicroWirelesCommu = 3,
    }
    enum QGDW1376_2ComSpeedUnit {
        bps = 0,
        kbps = 1
    };
    enum QGDW1376_2ErrorStatus : Byte {
        /// <summary>
        /// 通信超时
        /// </summary>
        TimeOut = 0,
        /// <summary>
        /// 无效数据单元
        /// </summary>
        InvalidDataUnit = 1,
        /// <summary>
        /// 长度错误
        /// </summary>
        InvalidLength,
        /// <summary>
        /// 校验错误
        /// </summary>
        CheckError,
        /// <summary>
        /// 信息类不存在
        /// </summary>
        InvalidInfoClass,
        /// <summary>
        /// 格式错误
        /// </summary>
        FormatError,
        /// <summary>
        /// 表号重复
        /// </summary>
        DupTableId,
        /// <summary>
        /// 表号不存在
        /// </summary>
        UnexistTableId,
        /// <summary>
        /// 电表应用层无应答
        /// </summary>
        AppUnrespone,
        /// <summary>
        /// 主节点忙
        /// </summary>
        /// <remarks>
        /// 主节点：集中器所在的本地通信模块
        /// </remarks>
        PrimaryNodeBusy,
        /// <summary>
        /// 主节点不支持此命令
        /// </summary>
        PrimaryNodeUnsupport,
        /// <summary>
        /// 从节点不应答
        /// </summary>
        SecondaryNodeUnresponse,
        /// <summary>
        /// 从节点不在网内
        /// </summary>
        SecondaryNodeNotInNet,
    }
    /// <summary>
    /// 376.2 信道状态类型
    /// </summary>
    enum QGDW1376_2_ChannelStatus {
        Busy,
        IDLE,
    }
    /// <summary>
    /// 376.2 命令状态
    /// </summary>
    enum QGDW1376_2_CmdStatus {
        Unhandled,
        Handled,
    }
    /// <summary>
    /// 主从状态
    /// </summary>
    enum QGDW1376_2_PrmStatus : Byte {
        Master,
        Slave
    }
    /// <summary>
    /// 方向状态
    /// </summary>
    enum QGDW1376_2_DirStatus : Byte {
        Downstream,
        Upstream
    }
    enum QGDW1376_2_CommuProtocolType {
        Apparent,
        DLT645_97,
        DLT645_2007,
        Reserve,
    }

    [Flags]
    enum QGDW1376_2_PeriodicMeterReadMode {
        Preserve = 0x0,
        ConcentratorMaster = 0x1,
        RouteMaster = 0x2,
    }
    //interface IQGDW1376_2 {
    //    Byte[] ToByte();
    //    #region 长度域
    //    UInt16 L {
    //        set;
    //        get;
    //    }
    //    #endregion
    //}

    abstract class QGDW1376_2 {
        public const Byte StartChar = 0x68;
        private List<Byte> StartChar_FIELD = new List<Byte> { 0x68 };
        public const Byte EndChar = 0x16;
        private List<Byte> EndChar_FIELD = new List<byte> { 0x16 };
        private const Int32 MaxLength = 65535;
        public static readonly UInt64 BroadCastAddr = 0x999999999999;
        /// <summary>
        /// 信息字段标识，目前默认均为 0；
        /// </summary>
        private const UInt16 InfoField = 0x0;

        public QGDW1376_2CommuWay CommuWay = QGDW1376_2CommuWay.BroadCarrCommu;


        #region 长度域
        /// <summary>
        /// 长度字段（两个字节 UInt16）只读。
        /// </summary>
        /// <remarks>
        /// 包括用户数据长度 L1 和 6 个字节的固定长度
        /// （起始字符、长度、控制域、校验和、结束字符），
        /// 长度L不大于65535。
        /// 用户数据包括：信息域+地址域+应用数据域(应用功能码+数据单元标识+数据单元）
        /// </remarks>
        public virtual UInt16 L {
            get {
                UInt16 tmp = (UInt16)(6 + this.R_FIELD.Count +  
                    Convert.ToByte(this.A_FIELD?.Count) + this.AFN_FIELD.Count + this.Fn_FIELD.Count + 
                    Convert.ToByte(this.DataUnit_FIELD?.Count));
                return tmp;
            }
        }
        private List<Byte> L_FIELD {
            get {
                return BitConverter.GetBytes(this.L).ToList();
            }
        }
        #endregion 长度域

        #region 控制域
        private List<Byte> C_FIELD = new List<byte>(1) { 0 };
        public Byte C {
            get => this.C_FIELD[0];
            set {
                this.C_FIELD[0] = value;
                this.PRM_FIELD = (Byte)((value << 1) >> 6);
                this.DIR_FIELD = (Byte)(value >> 7);
            }
        }
        /// <summary>
        /// 启动标志位
        /// </summary>
        /// <remarks>
        /// PRM=1：表示此帧报文来自启动站；PRM=0：表示此帧报文来自从动站
        /// </remarks>
        public QGDW1376_2_PrmStatus PRM {
            get => (QGDW1376_2_PrmStatus)((this.C_FIELD[0] << 1) >> 5);
            set {
                this.C_FIELD[0] = (Byte)((this.C_FIELD[0] & 0xbf) | ((Byte)value << 6));
                this.PRM_FIELD = (Byte)value;
            }
        }
        private Byte PRM_FIELD = (Byte)QGDW1376_2_PrmStatus.Master;
        /// <summary>
        /// 传输方向
        /// </summary>
        /// <remarks>
        /// DIR=0：表示此帧报文是由集中器发出的下行报文；DIR=1：表示此帧报文是由通信模块发出的上行报文。
        /// </remarks>
        public QGDW1376_2_DirStatus DIR {
            get => (QGDW1376_2_DirStatus)((this.C_FIELD[0] >> 7));
            set {
                this.DIR_FIELD = (Byte)value;
                this.C_FIELD[0] = (Byte)((this.C_FIELD[0] & 0x7f) | ((Byte)value << 7));
            }
        }
        private Byte DIR_FIELD;

        private Byte CommuWay_FIELD;
        public QGDW1376_2CommuWay COMWAY {
            get => (QGDW1376_2CommuWay)(this.C_FIELD[0] & 0x1f);
            set {
                this.CommuWay_FIELD = (Byte)value;
                this.C_FIELD[0] = (Byte)((this.C_FIELD[0] & 0xC0) | (Byte)value);
            }
        }
        #endregion  控制域

        #region 用户数据
        #region 信息域
        #region 公有属性
        /// <summary>
        /// 信息域：使用 64 bit 的无符号整型来代表 48 bit；
        /// 一般不建议直接设置信息域。默认情况下各字段均为 0。
        /// </summary>
        /// <remarks>
        /// 由于上下行不一致问题，访问 bit 字段的时候将损失 cached 优势，
        /// 但会提高 R 的设置性能。
        /// </remarks>
        public UInt64 R {
            set {
                List<Byte> tmplist = BitConverter.GetBytes(value).ToList();
                tmplist.RemoveRange(6, 2);
                this.R_FIELD = tmplist;

                this.RouteId_FIELD = Convert.ToBoolean(value & 0x1);
                // 附属节点标识为下行报文特有，此处省略
                this.CommuModelId_FIELD = Convert.ToBoolean(value & 0x2);
                this.RelayLevel_FIELD = Convert.ToByte((value & 0xf0) >> 4);
                this.ChannelId_FIELD = Convert.ToByte((value & 0xf00) >> 8);
                this.Seq_FIELD = Convert.ToByte((value & 0xff0000000000) >> 40);
            }
            get {
                Byte[] RArray = new Byte[8];
                this.R_FIELD.CopyTo(RArray);
                return BitConverter.ToUInt64(RArray, 0);
            }
        }
        protected List<Byte> R_FIELD = new List<byte>(6) { 0 };
        /// <summary>
        /// 路由标识：false(0) 表示通信模块带路由或工作在路由模式，true(1) 表示通信模块不带路由或工作在旁路模式。
        /// </summary>
        public Boolean RouteId {
            get => this.RouteId_FIELD;
            set {
                this.RouteId_FIELD = value;
                this.R = Convert.ToUInt64((this.R & ~0x1ul) | Convert.ToUInt64(value) << 0);
            }
        }
        private Boolean RouteId_FIELD;

        /// <summary>
        /// 通信模块标识：
        /// false(0) 表示对主节点的操作，此时无需地址域；
        /// true(1)表示对从节点操作；
        /// </summary>
        public Boolean CommuModuleId {
            get => this.CommuModelId_FIELD;
            set {
                this.CommuModelId_FIELD = value;
                this.R = Convert.ToUInt64((this.R & ~0x4ul) | Convert.ToUInt64(value) << 2);
            }
        }
        private Boolean CommuModelId_FIELD;

        /// <summary>
        /// 中继级别：取值范围0～15，0表示无中继。
        /// </summary>
        public Byte RelayLevel {
            get => this.RelayLevel_FIELD;
            set {
                this.RelayLevel_FIELD = value;
                this.R = Convert.ToUInt64((this.R & ~0xf0ul) | (Convert.ToUInt64(value) << 4));
            }
        }
        private Byte RelayLevel_FIELD;

        /// <summary>
        /// 信道标识：取值0～15，0表示不分信道、1～15依次表示第1～15信道。
        /// </summary>
        public Byte ChannelId {
            get => this.ChannelId_FIELD;
            set {
                this.ChannelId_FIELD = value;
                this.R = Convert.ToUInt64((this.R & ~0xf00ul) | (Convert.ToUInt64(value) << 8));
            }
        }
        private Byte ChannelId_FIELD;

        /// <summary>
        /// 报文序列号：用以匹配上、下行报文的请求应答对应关系，值从0～255，循环使用
        /// </summary>
        public Byte Seq {
            get => this.Seq_FIELD;
            set {
                this.Seq_FIELD = value;
                this.R = Convert.ToUInt64((this.R & ~0xff0000000000ul) | (Convert.ToUInt64(value) << 40));
            }
        }
        private Byte Seq_FIELD;
        #endregion 公有属性

        #region 下行
        /// <summary>
        /// 附加节点标记，仅下行可用
        /// </summary>
        public virtual Boolean StatelliteNodeId {
            set { throw new NotImplementedException(); }
            get { throw new NotImplementedException(); }
        }
        /// <summary>
        /// 冲突检测，仅下行可用
        /// </summary>
        public virtual Boolean ConflictDetection {
            set { throw new NotImplementedException(); }
            get { throw new NotImplementedException(); }
        }
        /// <summary>
        /// 纠错编码标识
        /// </summary>
        public virtual Byte ErrorCorrectCodeId {
            set { throw new NotImplementedException(); }
            get { throw new NotImplementedException(); }
        }
        /// <summary>
        /// 预计应答字节数
        /// </summary>
        /// <remarks>
        /// 用于计算延时等待事件；为 0 时，延时等待时间为默认时间
        /// </remarks>
        public virtual Byte PredicateReplyNumByte {
            set { throw new NotImplementedException(); }
            get { throw new NotImplementedException(); }
        }
        /// <summary>
        /// 通信速率
        /// </summary>
        public virtual UInt16 CommuSpeed {
            set { throw new NotImplementedException(); }
            get { throw new NotImplementedException(); }
        }
        /// <summary>
        /// 通信单位
        /// </summary>
        public virtual QGDW1376_2ComSpeedUnit CommuSpeedUnit {
            set { throw new NotImplementedException(); }
            get { throw new NotImplementedException(); }
        }
        #endregion

        #region 上行
        /// <summary>
        /// 实测相线标识：实测从节点逻辑主信道所在电源相别，0为不确定，1～3依次表示相别为第1相、第2相、第3相。
        /// </summary>
        public virtual Byte ActualPhaseLineId {
            set { throw new NotImplementedException(); }
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// 电表通道特征：描述目的节点电表通道的特征，取值范围0～15，
        /// 0保留，
        /// 1为物理信道为单相供电，逻辑信道为单信道；
        /// 2为物理信道为单相供电，逻辑信道为两信道；
        /// 3为物理信道为单相供电，逻辑信道为三信道；
        /// 4为物理信道为三相供电，逻辑信道为三信道。
        /// </summary>
        public virtual Byte MeterChannelCharacter {
            set { throw new NotImplementedException(); }
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// 末级命令信号品质：分为15级，取值范围0～15，0表示无信号品质，1表示最低品质。
        /// </summary>
        public virtual Byte FinalCmdSigQuality {
            set { throw new NotImplementedException(); }
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// 末级应答信号品质：分为15级，取值范围0～15，0表示无信号品质，1表示最低品质。
        /// </summary>
        public virtual Byte FinalRepSigQuality {
            set { throw new NotImplementedException(); }
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// 事件标志：为0时无上报事件，为1时有上报事件
        /// </summary>
        public virtual Byte EventFlag {
            set { throw new NotImplementedException(); }
            get { throw new NotImplementedException(); }
        }
        #endregion 上行

        #endregion 信息域

        #region 地址域
        /// <summary>
        /// 设置地址域。如果通信模块标识为 false（0）则返回 null。
        /// 地址域 A 包含 A1, A2, A3。优先设置 A1，其次 A3，最后 A2。
        /// 即若长度小于 3 将会舍弃 A2，小于 2 将会舍弃 A3。
        /// 所以若想单独设置，请单独使用 A1, A2, A3 属性。
        /// </summary>
        public UInt64[] A {
            get {
                if (this.CommuModuleId == false || this.A_FIELD.Count < 6) return null;
                Byte[] A_Arry = new byte[8];
                UInt64[] result = new UInt64[this.A_FIELD.Count / 6];
                for (int i = 0; i < this.A_FIELD.Count / 6; i++) {
                    this.A_FIELD.CopyTo(i * 6, A_Arry, 0, 6);
                    result[i] = BitConverter.ToUInt64(A_Arry, 0);
                }
                return result;
            }
            set {
                if (this.A_FIELD == null) {
                    this.A_FIELD = new List<byte>(value.Length * 6);
                } else {
                    this.A_FIELD.Clear();
                }
                foreach (UInt64 addr in value) {
                    List<Byte> tmplist = BitConverter.GetBytes(addr).ToList();
                    tmplist.RemoveRange(6, 2);
                    this.A_FIELD.AddRange(tmplist);
                }
                if (value.Length == 0) this.A1_FIELD = null;
                else this.A1 = value[0];
                if (value.Length <= 1) this.A3_FIELD = null;
                else this.A3 = value[value.Length - 1];
                if (value.Length <= 2) this.A2_FIELD = null;
                else this.A2_FIELD = this.A_FIELD.GetRange(6, this.A_FIELD.Count - 6);
            }
        }
        protected List<Byte> A_FIELD = new List<byte>(0);

        /// <summary>
        /// 源地址
        /// </summary>
        /// <remarks>
        /// 传输数据帧的起始发送方的节点 MAC 地址
        /// </remarks>
        public UInt64? A1 {
            get {
                if (this.CommuModuleId == false || this.A1_FIELD == null) return null;
                Byte[] A1_Array = new Byte[8];
                this.A1_FIELD.CopyTo(0, A1_Array, 0, 6);
                return BitConverter.ToUInt64(A1_Array, 0);
            }
            set {
                if (this.A1_FIELD != null) {
                    this.A_FIELD.RemoveRange(0, 6);
                }
                List<Byte> tmp = BitConverter.GetBytes(value.Value).ToList();
                tmp.RemoveRange(6, 2);
                this.A1_FIELD = tmp;
                this.A_FIELD.InsertRange(0, this.A1_FIELD);
            }
        }
        private List<Byte> A1_FIELD;
        /// <summary>
        /// 中继地址
        /// </summary>
        /// <remarks>
        /// 传输数据帧时进行中继传送的节点 MAC 地址
        /// </remarks>
        public UInt64[] A2 {
            get {
                if (this.CommuModuleId == false || this.A2_FIELD == null) return null;
                UInt64[] result = new UInt64[this.A2_FIELD.Count / 6];
                Byte[] tmp = new Byte[8];
                for (int i = 0; i < result.Length; i++) {
                    this.A2_FIELD.CopyTo(i * 6, tmp, 0, 6);
                    result[i] = BitConverter.ToUInt64(tmp, 0);
                }
                return result;
            }
            set {
                if (this.A2_FIELD == null) {
                    this.A2_FIELD = new List<byte>(value.Length * 6);
                } else {
                    this.A_FIELD.RemoveRange(6, this.A_FIELD.Count - 12);
                }
                List<Byte> tmplist;
                foreach (UInt64 addr in value) {
                    tmplist = BitConverter.GetBytes(addr).ToList();
                    tmplist.RemoveRange(6, 2);
                    this.A2_FIELD.AddRange(tmplist);
                }
                this.A_FIELD.InsertRange((this.A1_FIELD == null ? 0 : 1) * 6, this.A2_FIELD);
            }
        }
        private List<Byte> A2_FIELD;
        /// <summary>
        /// 目的地址
        /// </summary>
        /// <remarks>
        /// 传输数据帧的最终接收方的节点 MAC 地址
        /// </remarks>
        public UInt64? A3 {
            get {
                if (this.CommuModuleId == false || this.A3_FIELD == null) return null;
                Byte[] result = new Byte[8];
                this.A_FIELD.CopyTo(this.A_FIELD.Count - 6, result, 0, 6);
                return BitConverter.ToUInt64(result, 0);
            }
            set {
                if (this.A3_FIELD != null) {
                    this.A_FIELD.RemoveRange(this.A_FIELD.Count - 6, 6);
                }
                List<Byte> tmplist = BitConverter.GetBytes(value.Value).ToList();
                tmplist.RemoveRange(6, 2);
                this.A_FIELD.AddRange(tmplist);
                this.A3_FIELD = tmplist;
            }
        }
        private List<Byte> A3_FIELD;

        #endregion 地址域

        #region 应用数据域
        /// <summary>
        /// 应用层功能码 AFN 由一字节组成
        /// </summary>
        public Byte AFN {
            set { this.AFN_FIELD[0] = value; }
            get => this.AFN_FIELD[0];
        }
        private List<Byte> AFN_FIELD = new List<byte>(1) { 0 };
        /// <summary>
        /// 数据单元标识
        /// 信息类 DT 由信息类元 DT1 和信息类组 DT2 两个字节构成。
        /// 目前允许的值范围为 1~ 241 对应 F1 ~F241。
        /// 推荐直接访问 Fn 属性
        /// </summary>
        /// <remarks>
        /// 数据单元标识 Fn == 信息类 DT == 信息类组 + 信息类元，但用户一般只关心数据单元标识即可。
        /// </remarks>
        private UInt16 DT {
            get {
                Byte dt2 = this.Fn_FIELD[1];
                Byte dt1 = this.Fn_FIELD[0];
                UInt16 result = Convert.ToUInt16(dt2 * 8);
                for (UInt16 i = 0; i < 8; i++) {
                    if (Convert.ToBoolean(dt1 & (1u << (Byte)i))) {
                        result += Convert.ToUInt16(i + 1);
                        return result;
                    }
                }
                throw new NotSupportedException("无法确定 Fn");
            }
            set {
                Byte dt2 = Convert.ToByte((value - 1) / 8);
                Byte dt1 = (Byte)(1 << ((value - 1) % 8));  // mmp
                this.Fn_FIELD[0] = dt1;
                this.Fn_FIELD[1] = dt2;
            }
        }
        private List<Byte> Fn_FIELD = new List<Byte>(2) { 0, 0 };

        /// <summary>
        /// 信息类标识
        /// </summary>
        public UInt16 Fn {
            set => this.DT = value;
            get => this.DT;
        }
        /// <summary>
        /// 数据单元
        /// </summary>
        public Byte[] DataUnit {
            get => this.DataUnit_FIELD?.ToArray();
            set => this.DataUnit_FIELD = value?.ToList();
        }
        protected List<Byte> DataUnit_FIELD;
        #endregion 应用数据域
        public virtual BitArray ChannelCmdStatus { get; set; }
        public virtual Byte? WaitTime { get; set; }
        public virtual Byte? ErrorStatus { get; set; }
        public virtual Byte? TestCommuSpeed { get; set; }
        public virtual UInt64? TestDestAddr { get; set; }
        public virtual QGDW1376_2_CommuProtocolType CommuProtocolType { get; set; }
        public virtual Byte? TestLength { get; set; }
        public virtual Byte[] TestPacketContent { get; set; }
        public virtual QGDW1376_2QueryCommuWay QueryCommuWay { get; set; }
        public virtual Boolean QueryRouteManageWay { get; set; }
        public virtual Boolean QueryMeasPointInfoModel { get; set; }
        public virtual QGDW1376_2_PeriodicMeterReadMode QueryPeriodicMeterReadMode { get; set; }
        public virtual Byte QueryChannelNum { get; set; }
        public virtual UInt64 QueryPrimaryNodeAddr { get; set; }
        public virtual UInt64 Ctrl_SetPrimaryNodeAddr { get; set; }
        #endregion 用户数据

        #region 帧校验和
        /// <summary>
        /// 帧校验和：控制域和用户数据区所有字节的 8 位算术和
        /// </summary>
        public Byte CS {
            get {
                Byte tmp = this.C;
                foreach(Byte data in this.R_FIELD) {
                    tmp += data;
                }
                if(this.DataUnit != null) {
                    foreach (Byte data in this.DataUnit) {
                        tmp += data;
                    }
                }
                foreach (Byte data in this.A_FIELD) {
                    tmp += data;
                }
                tmp += this.AFN;
                foreach (Byte data in this.Fn_FIELD) {
                    tmp += data;
                }
                return tmp;
            }
            private set {
            }
        }
        private List<Byte> CS_FIELD {
            get {
                List<Byte> tmp = new List<Byte>(1) {
                    this.CS
                };
                return tmp;
            }
        }
        #endregion

        public QGDW1376_2() { }

        public QGDW1376_2(
            Byte AFN, Byte Fn
            ) {
            this.AFN = AFN; this.Fn = Fn;
        }

        //public static Object Parser(Byte[] packet) {
        //    packet[3]
        //    return null;
        //}


        virtual public Byte[] ToByte() {
            List<Byte> tmp = new List<Byte>(this.L);

            tmp = (tmp.Concat(this.StartChar_FIELD).Concat(this.L_FIELD).Concat(this.C_FIELD).Concat(this.R_FIELD).Concat(this.A_FIELD).Concat(this.AFN_FIELD)).Concat(this.Fn_FIELD).ToList();
            if(this.DataUnit_FIELD != null) {
                tmp = tmp.Concat(this.DataUnit_FIELD).ToList();
            }
            tmp = tmp.Concat(this.CS_FIELD).Concat(this.EndChar_FIELD).ToList();
            return tmp.ToArray();
        }

    }


    class QGDW1376_2_Downstream : QGDW1376_2 {
        #region 信息域
        /// <summary>
        /// 附属节点标识：指从节点附属节点标识，0表示无附加节点，1表示有附加节点。
        /// </summary>
        public override Boolean StatelliteNodeId {
            get => Convert.ToBoolean((base.R & 0x2ul) >> 1);
            set {
                this.StatelliteNodeId_FIELD = value;
                base.R = Convert.ToUInt64((base.R & ~0x2ul) | Convert.ToUInt64(value) << 1);
            }
        }
        private Boolean StatelliteNodeId_FIELD;
        /// <summary>
        /// 冲突检测：0表示不进行冲突检测，1表示要进行冲突检测。
        /// </summary>
        public override Boolean ConflictDetection {
            get => Convert.ToBoolean((base.R & 0x8ul) >> 3);
            set {
                this.ConflictDetection_FIELD = value;
                base.R = Convert.ToUInt64((base.R & ~0x8ul) | (Convert.ToUInt64(value) << 3));
            }
        }
        private Boolean ConflictDetection_FIELD;
        /// <summary>
        /// 纠错编码标识：取值范围0～15，0表示信道未编码，1表示RS编码，2～15保留
        /// </summary>
        public override Byte ErrorCorrectCodeId {
            get => Convert.ToByte((base.R & 0xf000ul) >> 12);
            set {
                this.ErrorCorrectCodeId_FIELD = value;
                base.R = Convert.ToUInt64((base.R & ~0xf000ul) | (Convert.ToUInt64(value) << 12));
            }
        }
        private Byte ErrorCorrectCodeId_FIELD;
        /// <summary>
        /// 预计应答字节数
        /// </summary>
        public override Byte PredicateReplyNumByte {
            get => Convert.ToByte((base.R & 0xff0000ul) >> 16);
            set {
                this.PredicateReplyNumByte_FIELD = value;
                base.R = Convert.ToUInt64((base.R & ~0xff0000ul) | (Convert.ToUInt64(value) << 16));
            }
        }
        private Byte PredicateReplyNumByte_FIELD;
        /// <summary>
        /// 通信速率
        /// </summary>
        private UInt16 CommuSpeed_FIELD;
        public override UInt16 CommuSpeed {
            get => Convert.ToUInt16((base.R & 0x7ff000000) >> 24);
            set {
                this.CommuSpeed_FIELD = value;
                base.R = Convert.ToUInt64((base.R & ~0x7ff000000ul) | (Convert.ToUInt64(value) << 24));
            }
        }
        /// <summary>
        /// 速率单位标识：0表示bps，1表示kbps。
        /// </summary>
        public override QGDW1376_2ComSpeedUnit CommuSpeedUnit {
            get => (QGDW1376_2ComSpeedUnit)((base.R & 0x800000000ul) >> 39);
            set {
                this.CommuSpeedUnit_FIELD = value;
                base.R = Convert.ToUInt64((base.R & ~0x800000000ul) | (Convert.ToUInt64(value) << 39));
            }
        }
        private QGDW1376_2ComSpeedUnit CommuSpeedUnit_FIELD;
        #endregion 信息域


        public QGDW1376_2_Downstream() {
            this.DIR = QGDW1376_2_DirStatus.Downstream;
            this.PRM = QGDW1376_2_PrmStatus.Master;
        }
        public QGDW1376_2_Downstream(Byte AFN, Byte Fn) : this() {
            this.AFN = AFN;
            this.Fn = Fn;
        }
        public QGDW1376_2_Downstream(Byte AFN, Byte Fn, Byte[] data) : this() {
            this.AFN = AFN;
            this.Fn = Fn;
            this.DataUnit = data;
        }

        public override byte[] ToByte() {
            return base.ToByte();
        }

    }

    class QGDW1376_2_Upstream : QGDW1376_2 {
        #region 信息域
        /// <summary>
        /// 实测相线标识：实测从节点逻辑主信道所在电源相别，0为不确定，1～3依次表示相别为第1相、第2相、第3相。
        /// </summary>
        public override Byte ActualPhaseLineId {
            get => Convert.ToByte((base.R & 0xf0000ul) >> 16);
            set {
                this.ActualPhaseLineId_FIELD = value;
                base.R = Convert.ToUInt64((base.R & ~0xf0000ul) | (Convert.ToUInt64(value) << 16));
            }
        }
        private Byte ActualPhaseLineId_FIELD;

        /// <summary>
        /// 电表通道特征：描述目的节点电表通道的特征，取值范围0～15，
        /// 0保留，
        /// 1为物理信道为单相供电，逻辑信道为单信道；
        /// 2为物理信道为单相供电，逻辑信道为两信道；
        /// 3为物理信道为单相供电，逻辑信道为三信道；
        /// 4为物理信道为三相供电，逻辑信道为三信道。
        /// </summary>
        public override Byte MeterChannelCharacter {
            get => Convert.ToByte((base.R & 0xf00000ul) >> 20);
            set {
                this.MeterChannelCharacter_FIELD = value;
                base.R = Convert.ToUInt64((base.R & ~0xf00000ul) | (Convert.ToUInt64(value) << 20));
            }
        }
        private Byte MeterChannelCharacter_FIELD;

        /// <summary>
        /// 末级命令信号品质：分为15级，取值范围0～15，0表示无信号品质，1表示最低品质。
        /// </summary>
        public override Byte FinalCmdSigQuality {
            get => Convert.ToByte((base.R & 0xf000000ul) >> 24);
            set {
                this.FinalCmdSigQuality_FIELD = value;
                base.R = Convert.ToUInt64((base.R & ~0xf000000ul) | (Convert.ToUInt64(value) << 24));
            }
        }
        private Byte FinalCmdSigQuality_FIELD;

        /// <summary>
        /// 末级应答信号品质：分为15级，取值范围0～15，0表示无信号品质，1表示最低品质。
        /// </summary>
        public override Byte FinalRepSigQuality {
            get => Convert.ToByte((base.R & 0xf0000000ul) >> 28);
            set {
                this.FinalRepSigQuality_FIELD = value;
                base.R = Convert.ToUInt64((base.R & ~0xf0000000ul) | (Convert.ToUInt64(value) << 28));
            }
        }
        private Byte FinalRepSigQuality_FIELD;

        /// <summary>
        /// 事件标志：为0时无上报事件，为1时有上报事件
        /// </summary>
        public override Byte EventFlag {
            get => Convert.ToByte((base.R & 0x100000000ul) >> 32);
            set {
                this.EventFlag_FIELD = value;
                base.R = Convert.ToUInt64((base.R & ~0x100000000ul) | (Convert.ToUInt64(value) << 32));
            }
        }
        private Byte EventFlag_FIELD;

        #endregion 信息域

        public QGDW1376_2_Upstream() {
            this.DIR = QGDW1376_2_DirStatus.Upstream;
        }
        public QGDW1376_2_Upstream(Byte AFN, Byte Fn) {
            this.AFN = AFN;
            this.Fn = Fn;
        }
    }
    /// <summary>
    /// 确认/否认 AFN=0x0 
    /// </summary>
    /// <remarks>
    /// CommuModuleId = 0，故没有地址域。
    /// </remarks>
    class QGDW1376_2_ANACK : QGDW1376_2_Upstream {

        public QGDW1376_2_ANACK() {
            this.CommuModuleId = false;
            this.AFN = 0x0;
        }

    }

    class QGDW1376_2_NACK : QGDW1376_2_ANACK {
        public QGDW1376_2_NACK() => this.Fn = 0x2;
        #region 数据单元
        public override Byte? ErrorStatus {
            get => this.DataUnit?[0];
            set {
                if (this.DataUnit == null || this.DataUnit.Length > 1) {
                    this.DataUnit = new Byte[1];
                }
                this.DataUnit[0] = value.Value;
            }
        }
        #endregion
    }

    class QGDW1376_2_ACK : QGDW1376_2_ANACK {
        public QGDW1376_2_ACK() => this.Fn = 0x1;
        #region 数据单元
        public override BitArray ChannelCmdStatus {
            get {
                if (this.DataUnit_FIELD.Count <= 3) {
                    return null;
                } else {
                    return new BitArray(Convert.ToUInt16(this.DataUnit_FIELD.GetRange(0, 2).ToArray()));
                }


            }
            set {
                if (this.DataUnit == null) {
                    this.DataUnit = new Byte[3];
                }
                value.CopyTo(this.DataUnit, 0);
            }
        }

        public override Byte? WaitTime {
            set {
                if (this.DataUnit == null) {
                    this.DataUnit = new Byte[3];
                }
                this.DataUnit[2] = value.Value;
            }
            get => this.DataUnit?[2];
        }
        #endregion

    }

    class QGDW1376_2_LinkfaceDect : QGDW1376_2_Downstream {
        public QGDW1376_2_LinkfaceDect() {
            this.AFN = 0x04;
            this.CommuModuleId = false; // Fn = 2 时，有通信模块标识 
        }
    }

    class QGDW1376_2_LinkfaceDect_LocalModuleCommuTest : QGDW1376_2_LinkfaceDect {
        public QGDW1376_2_LinkfaceDect_LocalModuleCommuTest() {
            this.Fn = 1;
        }

        public override Byte? TestCommuSpeed {
            get {
                if (this.DataUnitCheck()) {
                    return this.DataUnit[0];
                } else return null;
            }
            set {
                if (!this.DataUnitCheck()) {
                    this.DataUnit = new Byte[9];
                }
                this.DataUnit[0] = Convert.ToByte(value);
            }
        }

        public override UInt64? TestDestAddr {
            get {
                if (this.DataUnitCheck()) {
                    Byte[] tmp = new Byte[8];
                    this.DataUnit_FIELD.GetRange(1, 6).ToArray().CopyTo(tmp, 0);
                    return BitConverter.ToUInt64(tmp, 0);
                } else {
                    return null;
                }
            }
            set {
                if (!this.DataUnitCheck()) {
                    this.DataUnit = new Byte[9];
                }
                Array.Copy(
                    BitConverter.GetBytes(Convert.ToUInt64(value)), 0,
                    this.DataUnit, 1, 6
                    );
            }
        }

        public override QGDW1376_2_CommuProtocolType CommuProtocolType {
            get {
                if (this.DataUnitCheck()) {
                    return (QGDW1376_2_CommuProtocolType)this.DataUnit[7];
                } else {
                    return QGDW1376_2_CommuProtocolType.Reserve;
                }
            }
            set {
                if (!this.DataUnitCheck()) {
                    this.DataUnit = new Byte[9];
                }
                this.DataUnit[7] = Convert.ToByte(value);
            }
        }

        public override Byte? TestLength {
            get {
                if (this.DataUnitCheck()) {
                    return this.DataUnit[8];
                } else {
                    return null;
                }
            }
            set {
                if (!this.DataUnitCheck()) {
                    this.DataUnit = new Byte[9];
                }
                this.DataUnit[8] = Convert.ToByte(value);
            }

        }

        public override Byte[] TestPacketContent {
            get {
                if (DataUnitCheck()) {
                    return this.DataUnit_FIELD.GetRange(9, Convert.ToInt32(this.TestLength)).ToArray();
                } else {
                    return null;
                }
            }
            set {
                this.TestLength = (Byte)value.Length;
                this.DataUnit_FIELD.AddRange(value);
            }
        }

        private Boolean DataUnitCheck() {
            if(this.DataUnit == null) {
                return false;
            }
            if (this.DataUnit.Length < (9 + Convert.ToInt32(this.DataUnit[8]))) {
                return false;
            } else return true;
        }
    }

    class QGDW1376_2_RouteCtrl : QGDW1376_2_Downstream {
        public QGDW1376_2_RouteCtrl() {
            this.AFN = 0x12;
        }
    }

    /// <summary>
    /// 路由控制 -- 暂停，无数据单元
    /// </summary>
    class QGDW1376_2_RouteCtrlSuspend : QGDW1376_2_RouteCtrl {
        public QGDW1376_2_RouteCtrlSuspend() {
            this.Fn = 0x2;
            this.DataUnit = null;
            this.RouteId = true;
            this.CommuModuleId = false;
        }
    }

    class QGDW1376_2_Query_Downstream : QGDW1376_2_Downstream {
        public QGDW1376_2_Query_Downstream() {
            this.AFN = 0x03;
            this.CommuModuleId = false;
        }
    }

    class QGDW1376_2_Query_LocalCommuModuleRunModel_Downstream : QGDW1376_2_Query_Downstream{
        public QGDW1376_2_Query_LocalCommuModuleRunModel_Downstream() {
            this.Fn = 10;
        }
    }

    class QGDW1376_2_Query_Upstream : QGDW1376_2_Upstream {
        public QGDW1376_2_Query_Upstream() {
            this.AFN = 0x03;
            this.CommuModuleId = false;
        }
    }

    class QGDW1376_2_Query_LocalCommuModuleRunModel_Upstream : QGDW1376_2_Query_Upstream{
        public QGDW1376_2_Query_LocalCommuModuleRunModel_Upstream() {
            this.Fn = 10;
        }
        /// <summary>
        /// 主节点返回的通信方式，和控制字中的通信方式表示不同
        /// </summary>
        public override QGDW1376_2QueryCommuWay QueryCommuWay {
            get {
                return (QGDW1376_2QueryCommuWay)(this.DataUnit[0] & 0xf);
            }
        }
        /// <summary>
        /// 路由管理方式。
        /// true：无路由管理功能
        /// false：有路由管理功能·
        /// </summary>
        public override Boolean QueryRouteManageWay {
            get {
                return Convert.ToBoolean((this.DataUnit[0] >> 4) & 0x1);
            }
        }
        /// <summary>
        /// 测量点信息模式：true 表示需要下发测量点信息，false 表示不需要下发测量点信息
        /// </summary>
        public override Boolean QueryMeasPointInfoModel {
            get {
                return Convert.ToBoolean((this.DataUnit[0] >> 5) & 0x1);
            }
        }
        public override QGDW1376_2_PeriodicMeterReadMode QueryPeriodicMeterReadMode {
            get {
                return (QGDW1376_2_PeriodicMeterReadMode)(this.DataUnit[0] >> 6);
            }
        }

        /// <summary>
        /// 本地通信支持的信道总数量，0 表示不需要操作
        /// </summary>
        public override Byte QueryChannelNum {
            get {
                return (Byte)(this.DataUnit[2] & 0x7);
            }
        }

        public override UInt64 QueryPrimaryNodeAddr {
            get {
                Byte[] tmp = new Byte[8];
                Array.Copy(this.DataUnit, 15, tmp, 0, 6);
                return BitConverter.ToUInt64(tmp, 0);
            }
        }
    }

    class QGDW1376_2_QueryPrimaryNodeAddr_Downstream : QGDW1376_2_Query_Downstream {
        public QGDW1376_2_QueryPrimaryNodeAddr_Downstream() {
            this.Fn = 4;
            this.DataUnit = null;
        }
    }

    class QGDW1376_2_QueryPrimaryNodeAddr_Upstream : QGDW1376_2_Query_Upstream {
        public QGDW1376_2_QueryPrimaryNodeAddr_Upstream() {
            this.Fn = 4;
        }
        public override UInt64 QueryPrimaryNodeAddr {
            get {
                Byte[] tmp = new Byte[8];
                this.DataUnit.CopyTo(tmp, 0);
                return BitConverter.ToUInt64(tmp, 0);
            }
        }
    }

    class QGDW1376_2_Ctrl : QGDW1376_2_Downstream {
        public QGDW1376_2_Ctrl() {
            this.AFN = 0x5;
        }
    }
    class QGDW1376_2_Ctrl_SetPrimaryNodeAddr : QGDW1376_2_Ctrl {
        public QGDW1376_2_Ctrl_SetPrimaryNodeAddr() {
            this.Fn = 1;
        }
        public override UInt64 Ctrl_SetPrimaryNodeAddr {
            set {
                Array.Copy(BitConverter.GetBytes(value), this.DataUnit, 6);
            }
        }
    }

    class QGDW1376_2_C {
        public readonly QGDW1376_2_DirStatus DIR;
        public readonly QGDW1376_2_PrmStatus PRM;
        public readonly QGDW1376_2CommuWay CommuWay;
        public QGDW1376_2_C(Byte value) {
            this.DIR = (QGDW1376_2_DirStatus)(value >> 7);
            this.PRM = (QGDW1376_2_PrmStatus)((value << 1) >> 6);
            this.CommuWay = (QGDW1376_2CommuWay)(value & 0x1f);
        }
    }

    class QGDW1376_2_R {
        public readonly Boolean CommuModuleId;
        public readonly Byte RealyLevel;
        public QGDW1376_2_R(UInt64 value) {
            this.CommuModuleId = Convert.ToBoolean((value & 0x4) >> 2);
            this.RealyLevel = (Byte)((value & 0xf0) >> 4);
        }
    }
    class QGDW1376_2_Fn {
        public readonly Byte Fn;
        public QGDW1376_2_Fn(Byte DT1, Byte DT2) {
            int index = 0;
            for(; index < 8; index++) {
                if((DT1 & (0x1 << index)) != 0) {
                    break;
                }
            }
            this.Fn = (Byte)((index + 1) + (DT2 * 8));
        }
    }

    static class QGDW1376_2_Factory {
        /// <summary>
        /// 创建 QGDW1376_2 报文对象
        /// </summary>
        /// <param name="AFN"></param>
        /// <param name="Fn"></param>
        /// <returns></returns>
        /// <remarks>
        /// 对于具有默认方向的报文，可以使用本工厂来创建，如有特殊要求可使用对应的重载函数。
        /// </remarks>
        public static QGDW1376_2 CreatePacket(UInt16 AFN, Byte Fn) {
            UInt16 id = (UInt16)((AFN << 8) + Fn);
            switch (id) {
                case 0x1202: return new QGDW1376_2_RouteCtrlSuspend();
                default: return null;
            }
        }
        /// <summary>
        /// 创建 QGDW1376_2 报文对象
        /// </summary>
        /// <param name="AFN">功能码</param>
        /// <param name="Fn">数据单元标识</param>
        /// <param name="dir">上行或下行</param>
        /// <returns>QGDW1276_2 对象</returns>
        public static QGDW1376_2 CreatePacket(Byte AFN, Byte Fn, QGDW1376_2_DirStatus dir) {
            UInt16 id = (UInt16)((AFN << 8) + Fn);
            switch (id) {
                case 0x1202: {
                        return new QGDW1376_2_RouteCtrlSuspend();
                    } // 路由控制暂停
                case 0x0501: {
                        return new QGDW1376_2_Ctrl_SetPrimaryNodeAddr();
                    } // 设置主节点地址
                case 0x0403: {
                        return new QGDW1376_2_LinkfaceDect_LocalModuleCommuTest();
                    } // 链路检测.本地模块通信测试
                case 0x0304: { 
                        if (dir == QGDW1376_2_DirStatus.Downstream)
                            return new QGDW1376_2_QueryPrimaryNodeAddr_Downstream();
                        else return new QGDW1376_2_QueryPrimaryNodeAddr_Upstream();
                    } // 查询主节点地址
                case 0x030a: {
                        if (dir == QGDW1376_2_DirStatus.Downstream)
                            return new QGDW1376_2_Query_LocalCommuModuleRunModel_Downstream();
                        else return new QGDW1376_2_Query_LocalCommuModuleRunModel_Upstream();
                    } // 本地通信模块运行模式查询
                case 0x0001: {
                        return new QGDW1376_2_ACK();
                    }
                case 0x0002: {
                        return new QGDW1376_2_NACK();
                    }
                default: return null;
            }
        }
        /// <summary>
        /// 通过字节数组来创建报文对象
        /// </summary>
        /// <param name="packet"></param>
        /// <returns></returns>
        public static QGDW1376_2 CreatePacket(Byte[] packet) {
            QGDW1376_2_C C = new QGDW1376_2_C(packet[3]);
            UInt16 L = (UInt16)(packet[1] + (packet[2] << 8));
            Byte[] R_Array = new byte[8];
            Array.Copy(packet, 4, R_Array, 0, 6);
            QGDW1376_2_R R = new QGDW1376_2_R(
                BitConverter.ToUInt64(R_Array, 0)
                );
            Byte AFN; Byte Fn;
            int index = 10;
            if (R.CommuModuleId) {
                index = 10 + (R.RealyLevel + 2) * 6 - 1;
            }
            AFN = packet[index];
            Fn = new QGDW1376_2_Fn(packet[index + 1], packet[index + 2]).Fn;

            QGDW1376_2 obj =  CreatePacket(AFN, Fn, C.DIR);
            obj.C = packet[3];
            obj.R = BitConverter.ToUInt64(R_Array, 0);
            if(obj.CommuModuleId) {
                Array.Copy(packet, 6, obj.A, 0, index - 5);
            }
            Byte[] tmp = new Byte[L - index - 5];
            Array.Copy(packet, index + 3, tmp, 0, L - index - 5);
            obj.DataUnit = tmp;
            //for(int i = 0; i < L-index-4; i++) {
            //    obj.DataUnit[i] = packet[index + 2 + i];
            //}
            if (obj.CS != packet[L - 2 ]) return null;
            else return obj;
        }
    }
}
